#
# $Id: tc_pdgen.rb 4 2007-09-27 09:38:28Z dinko.srkoc $
#

require 'test/unit'
require 'genus/pdgen'

# == +PDGen+ class tests.
#
# Instance of this class is used to process (read data from) a DSL file.
# The DSL file contains data from which persistence descriptor is built.
class TC_PDGen < Test::Unit::TestCase
  
  def runner(arg); lambda { pg = PersistenceDescriptorGenerator.new(arg); pg.exec; pg }; end
#  def runner(arg); Proc.new { pg = PersistenceDescriptorGenerator.new(arg); pg.exec; return pg }; end
  
  # Tests for +Struct+ classes
  
  def test_structs
    dbms = PersistenceDescriptorGenerator::Dbms.new
    assert_respond_to(dbms, :block)
    assert_respond_to(dbms, :type)
    assert_respond_to(dbms, :username)
    assert_respond_to(dbms, :password)
    assert_respond_to(dbms, :host)
    assert_respond_to(dbms, :port)
    assert_respond_to(dbms, :database)
    assert_respond_to(dbms, :server)
    
    options = PersistenceDescriptorGenerator::Options.new
    assert_respond_to(options, :sql_logging)
    assert_respond_to(options, :ddl_management)
    
    ds = PersistenceDescriptorGenerator::DataSource.new
    assert_respond_to(ds, :jndi)
    assert_respond_to(ds, :is_jta)
  end
  
  # Tests for acceptance of descriptor types.
  # Accepted descriptors: :jpa (default), :hibernate_xml, :hibernate_properties
  def test_descriptor_types
    assert_nothing_raised &runner('make')
    DESCRIPTOR_TYPES.each { |t| assert_nothing_raised &runner("make :descriptor => :#{t}") }

    assert_raise(RuntimeError, &runner('make :descriptor => :unknown'))
  end
  
  # Tests <tt>persistence_implementation_is</tt> - whether it accepts all/only supported
  # persistence implementors (which are given in <tt>PERSISTENCE_IMPLEMENTATIONS</tt> array).
  def test_persistence_implementations
    PERSISTENCE_IMPLEMENTATIONS.each do |pi|
      assert_nothing_raised &runner("make { persistence_implementation_is :#{pi} }")
    end
    assert_raise(RuntimeError, &runner('make { persistence_implementation_is :unknown_specific }'))
  end
  
  class ::PersistenceDescriptorGenerator
    attr_accessor :blocks      # ... used in test_collected_blocks
    attr_accessor :data_source # ... used in test_datasource
  end
  
  # Tests reading of <tt>data_source_is</tt>'s arguments.
  def test_datasource
    ds = runner("make { data_source_is 'ds_name' }").call.data_source
    assert_equal('ds_name', ds.jndi)
    assert_equal(true, ds.is_jta)

    ds = runner("make { data_source_is 'ds_name', :jta => true }").call.data_source
    assert_instance_of(String, ds.jndi)
    assert_equal(true, ds.is_jta)

    ds = runner("make { data_source_is 'ds_name', :jta => false }").call.data_source
    assert_equal(false, ds.is_jta)

    assert_raise(RuntimeError) { runner("make { data_source_is :jta => false }").call } # no JNDI name
  end
    
  # Tests whether the blocks in DSL are actually called
  # and calling only particular implementation specific blocks.
  def test_collected_blocks
    assert_raise(RuntimeError, &runner(<<-DBMSERR_END))
    make :descriptor => :hibernate_xml do
      dbms_is(:unknown) { puts "unsupported DBMS, should have raised exception before" }
    end
    DBMSERR_END
    
    pd = PersistenceDescriptorGenerator.new(<<-PD_END)
    make :descriptor => :hibernate_properties do
      persistence_implementation_is :toplink_specific
      @blocks = 'M'
      dbms_is(:postgresql) { @blocks << 'D' }
      toplink_specific { @blocks << 'T' }
      openjpa_specific { @blocks << 'O' } # should be silently ignored because impl. is toplink specific
    end
    PD_END
    
    pd.exec
    assert_equal('MDT', pd.blocks)
  end
  
end